unit uADODatabase;

interface

uses
  SysUtils, Classes, ActiveX, Variants, Windows, DB, ADODB, uDZSysUtils,
  uDZPersistent, uDZSerializer, uDZLinkList, uDzStream, uDZStr, uDZConfig,
  uDZDataSetSerializer, uDZThread, uDZTrace, uGxtTypes, uGxtSvcIntf, uCxtConst,
  uCxtTypes, uCxtPackage,uAppConfig, uAppLog, uCLDWProtocol, uLBMPTrackClient,
  uCxtDAL, uDBConnPool;

type
  TADODatabase = class(TDzInterfacedObject,
                            IAccountDatabase,
                            IVehicleDatabase,
                            ILbmpTrackDatabase)
  protected
    procedure UpdateLocTrace(Tracing: TLocTrace; Param: Pointer;
      Callback: TSimpleCallback);
      
    procedure PriVehicleOperation(Operation: TOperation; Vehicle: TVehicle;
      Param: Pointer; Callback: TSimpleCallback);
      
    procedure _GetShareVehicle(ObjType: TLBSObjectType; Filter: TShareVehicleFilter;
      PageIndex, PageSize: Integer; List: TDzPersistentList;
      Param: Pointer; Callback: TSimpleCallback);
  public
    constructor Create;
    destructor Destroy; override;

    {$region 'IAccountDatabase'}
    procedure GetAgencyInfo(CityCode: Integer; Agency: TAgency;
      Param: Pointer; Callback: TSimpleCallback);

    procedure AddAccount(UserInfo: TUserInfo; Param: Pointer; Callback: TSimpleCallback);

    procedure ModifyAccount(UserInfo: TUserInfo; Param: Pointer; Callback: TSimpleCallback);

    procedure ModifyPassword(UserID: Integer; const OldPwd, NewPwd: AnsiString;
      Param: Pointer; Callback: TSimpleCallback);
      
    procedure LockUserByID(UserID: Integer; const ComputerID: AnsiString;
      const Reason: WideString; Param: Pointer; Callback: TSimpleCallback);
            
    procedure GetUserInfo(const ComputerID, UserName: AnsiString; UserInfo: TUserInfo;
      Param: Pointer; Callback: TSimpleCallback);
      
    procedure GetUserLocatePoint(UserID: Integer; Param: Pointer; Callback: TSimpleCallback);
      
    procedure DecUserLocatePoint(UserID, Quantity: Integer;
      Param: Pointer; Callback: TSimpleCallback);

    procedure GetUserSmsPoint(UserID: Integer; Param: Pointer; Callback: TSimpleCallback);

    procedure DecUserSmsPoint(UserID, Quantity: Integer;
      Param: Pointer; Callback: TSimpleCallback);
    
    procedure SaveLogin(UserID: Integer; LoginTime: TDateTime; const Source,
      ComputerID: AnsiString; Param: Pointer; Callback: TSimpleCallback);

    procedure  SaveSms(const Sender, Recver, Content: WideString; SendTime: TDateTime;
      Param: Pointer; Callback: TSimpleCallback);

    procedure LockComputer(const ComputerID: AnsiString; const Reason: WideString;
      Param: Pointer; Callback: TSimpleCallback);

    procedure UnlockCompter(const ComputerID: AnsiString;
      Param: Pointer; Callback: TSimpleCallback);

    procedure IsComputerLocked(const ComputerID: AnsiString;
      Param: Pointer; Callback: TSimpleCallback);
    {$endregion}

    {$region 'IVehicleDatabase'}
    procedure GetPriVehicle(UserID, PageSize, PageIndex: Integer;
      Filter: TPriVehicleFilter; List: TDzPersistentList;
      Param: Pointer; Callback: TSimpleCallback);

    procedure GetShareVehicle(Filter: TShareVehicleFilter;
      PageIndex, PageSize: Integer; List: TDzPersistentList;
      Param: Pointer; Callback: TSimpleCallback);
      
    procedure GetWebShareVehicle(Filter: TWebShareVehicleFilter;
      PageIndex, PageSize: Integer; List: TDzPersistentList;
      Param: Pointer; Callback: TSimpleCallback);

    procedure RemovePriVehicle(List: TDzPersistentList;
      Param: Pointer; Callback: TSimpleCallback);

    procedure AddPriVehicle(Vehicle: TVehicle; Param: Pointer;
      Callback: TSimpleCallback);

    procedure ModifyPriVehicle(Vehicle: TVehicle; Param: Pointer;
      Callback: TSimpleCallback);

    procedure RemoveLocPerson(List: TDzPersistentList; Param: Pointer;
      Callback: TSimpleCallback);
    
    procedure AddLocPerson(Person: TLocPerson; Param: Pointer;
      Callback: TSimpleCallback);
    
    procedure ModifyLocPerson(Person: TLocPerson; Param: Pointer;
      Callback: TSimpleCallback);
    
    procedure GetLocPerson(UserID, PageIndex, PageSize: Integer; Filter: TLocPersonFilter;
      List: TDzPersistentList; Param: Pointer; Callback: TSimpleCallback);
      
    procedure SaveLocateResult(const Phone, Longitude, Latitude: AnsiString;
      const Address, CityName: WideString; CityID, UserID, ObjectID, Cost: Integer;
      LocType: TLbmpLocType; Param: Pointer; Callback: TSimpleCallback);

    procedure SetAutoLocTime(UserID, Hour: Integer; Param: Pointer; Callback: TSimpleCallback);
    
    procedure GetLocTrace(ID: Integer; Tracing: TLocTrace;
      Param: Pointer; Callback: TSimpleCallback);
    
    procedure AddLocTrace(Tracing: TLocTrace; Param: Pointer; Callback: TSimpleCallback);
    procedure RemoveLocTrace(ID: Integer; Param: Pointer; Callback: TSimpleCallback);
    procedure ModifyLocTrace(Tracing: TLocTrace; Param: Pointer; Callback: TSimpleCallback);
    
    procedure ModifyLBMPState(const Phone: AnsiString; State: Integer;
      Param: Pointer; Callback: TSimpleCallback);
    {$endregion}

    {$region 'ILBMPTrackDatabase'}
    procedure GetTrack(const Phone: string; list: TDzPersistentList;
      Param: Pointer; Callback: TSimpleCallback);

    procedure AddToTrack(const Phone: AnsiString; LocType: TLbmpLocType;
      LocTime: TDateTime; CityID: Integer; const Longitude, Latitude: AnsiString;
      const Address: WideString; Param: Pointer; Callback: TSimpleCallback);
      
    procedure ILBMPTrackDatabase.Get = GetTrack;
    procedure ILBMPTrackDatabase.Add = AddToTrack;
    {$endregion}
  end;

implementation

procedure SystemBusy(out Result: TFuncCallResult); inline;
begin
  Result.ErrCode := CXT_E_SYSTEM_BUSY;
  Result.ErrMsg := SSystemBusy;
end;

procedure CodecError(out Result: TFuncCallResult); inline;
begin
  Result.ErrCode := CXT_E_SERIALIZING;
  Result.ErrMsg := SCodecError;
end;

procedure AddCondition(Conds: TDzWideStrStream; const S: WideString);
begin
  if Conds.Position > 0 then Conds.WriteString(' and ');
  Conds.WriteString(S);
end;

procedure AddEqualCond(Conds: TDzWideStrStream; const Field, Value: WideString);
begin
  if Value = '' then Exit;
  if Conds.Position > 0 then Conds.WriteString(' and ');
  Conds.WriteString(Field);
  Conds.WriteString(' = '#39);
  Conds.WriteString(Value);
  Conds.WriteString(#39);
end;

procedure AddLikeCond(Conds: TDzWideStrStream; const Field, Value: WideString);
begin
  if Value = '' then Exit;
  if Conds.Position > 0 then Conds.WriteString(' and ');
  Conds.WriteString(Field);
  Conds.WriteString(' like '#39'%');
  Conds.WriteString(Value);
  Conds.WriteString('%'#39);
end;

{ TADODatabase }

procedure TADODatabase.AddAccount(UserInfo: TUserInfo; Param: Pointer;
  Callback: TSimpleCallback);
var
  Conn: TDBConnection;
  Result: TFuncCallResult;
begin
  Conn := ConnPool.GetConnection;
  if not Assigned(Conn) then
  begin
    SystemBusy(Result);
    Callback(Result, Param);
    Exit;
  end;
  with Conn, Conn.StoredProc, Parameters do
  try
    ProcedureName := '[cxt_56888_net].[dbo].[AddUser]';
    Clear;
    CreateParameter('Use_UserName',ftString, pdInput, 200, UserInfo.UserName);
    CreateParameter('Use_Type', ftInteger, pdInput, 4, UserInfo.UserType);
    CreateParameter('Use_PetName', ftString, pdInput, 20, null);
    CreateParameter('Use_RealName', ftString, pdInput, 20, UserInfo.RealName);
    CreateParameter('Use_Sex', ftInteger, pdInput, 4, UserInfo.Sex);
    CreateParameter('Use_IDCardNo', ftString, pdInput, 18, UserInfo.IDCardNo);
    CreateParameter('Use_Password', ftString, pdInput, 50, UserInfo.Password);
    CreateParameter('Use_Email', ftString, pdInput, 50, null);
    CreateParameter('Use_CityCode', ftInteger, pdInput, 4, UserInfo.CityCode);
    CreateParameter('Use_Tel', ftString, pdInput, 20, UserInfo.Telephone);
    CreateParameter('Use_TelExt', ftString, pdInput, 20, null);
    CreateParameter('Use_NetTel', ftString, pdInput, 20, null);
    CreateParameter('Use_Add', ftString, pdInput, 500, UserInfo.Address);
    CreateParameter('Use_Corp', ftString, pdInput, 500, UserInfo.CompanyName);
    CreateParameter('Use_DiskKeyNo', ftString, pdInput, 20, null);
    CreateParameter('Use_Img', ftString, pdInput, 20, '');
    CreateParameter('Use_MobileNo', ftString, pdInput, 20, UserInfo.MobilePhone);
    CreateParameter('Use_Url', ftString, pdInput, 100, UserInfo.Website);
    CreateParameter('ReturnCode', ftInteger, pdOutput, 4, null);
    CreateParameter('AgentName', ftString, pdOutput, 50, null);
    CreateParameter('AgentTel', ftString, pdOutput, 50, null);
    ExecStoredProc(Result.ErrCode, Result.ErrMsg, True);
    if Result.ErrCode = 0 then
    begin
      UserInfo.UserID := ParamValues['ReturnCode'];
      if UserInfo.UserID = -1 then
      begin
        Result.ErrCode := CXT_E_PRIMARYKEY_COLLISION;
        Result.ErrMsg := SUserNameExists;
      end
      else begin
        Result.WideStr := VarToWideStr(Parameters[19].Value);
        Result.ErrMsg := VarToWideStr(Parameters[20].Value);
      end;
    end;
    Callback(Result, Param);
  finally
    ConnPool.ReleaseConnection(Conn);
  end;
end;

procedure TADODatabase.AddLocPerson(Person: TLocPerson;
	Param: Pointer; Callback: TSimpleCallback);
var
  Conn: TDBConnection;
  Result: TFuncCallResult;
begin
  Conn := ConnPool.GetConnection;
  if not Assigned(Conn) then
  begin
    SystemBusy(Result);
    Callback(Result, Param);
    Exit;
  end;
  Result.NumProcessed := 0;
  with Conn, StoredProc, Parameters do
  try
    ProcedureName := '[cxt_56888_net].[dbo].[CarInfo_AddPeopleInfo]';
    Clear;
    CreateParameter('SuiCheShouJi',ftString, pdInput, 50, null);
    CreateParameter('SiJiXingMing', ftString, pdInput, 50, null);
    CreateParameter('Sex', ftString, pdInput, 2, null);
    CreateParameter('ZhuCeFou', ftInteger, pdInput, 4, -1);
    CreateParameter('BeiZhu', ftString, pdInput, 1000, null);
    CreateParameter('SuoShuYongHu', ftInteger, pdInput, 4, null);
    CreateParameter('ReturnCode', ftInteger, pdOutput, 4, null);
    Items[0].Value := Person.Phone;
    Items[1].Value := Person.Name;
    Items[2].Value := Person.Sex;
    Items[3].Value := -1;
    Items[4].Value := Person.Remark;
    Items[5].Value := Person.UserID;
    ExecStoredProc(Result.ErrCode, Result.ErrMsg, True);
    Callback(Result, Param);
  finally
    ConnPool.ReleaseConnection(Conn);
  end;
end;

procedure TADODatabase.AddLocTrace(Tracing: TLocTrace; Param: Pointer;
  Callback: TSimpleCallback);
begin
  UpdateLocTrace(Tracing, Param, Callback);
end;

procedure TADODatabase.PriVehicleOperation(Operation: TOperation; Vehicle: TVehicle;
  Param: Pointer; Callback: TSimpleCallback);
var
  Conn: TDBConnection;
  Result: TFuncCallResult;
begin
  Vehicle.StateCode := -1;
  Conn := ConnPool.GetConnection;
  if not Assigned(Conn) then
  begin
    SystemBusy(Result);
    Callback(Result, Param);
    Exit;
  end;
  try
    case Operation of
      opAdd: Conn.StoredProc.ProcedureName :=
        '[cxt_56888_net].[dbo].[CarInfo_AddCarInfo]';
      opModify: Conn.StoredProc.ProcedureName :=
        '[cxt_56888_net].[dbo].[CarInfo_UpdateCarInfo]';
    end;
    with Conn.StoredProc.Parameters, Vehicle do
    begin
      Clear;
      CreateParameter('CheLiangBianHao', ftInteger, pdInput, 4, GUID);
      CreateParameter('SuiCheShouJi', ftString, pdInput, 50, Phone);
      CreateParameter('SiJiXingMing', ftString, pdInput, 50, SiJiXingMing);
      CreateParameter('ChePaiHaoMa', ftString, pdInput, 50, Name);
      CreateParameter('QiWangLiuXiang', ftString, pdInput, 50, QiWangLiuXiang);
      CreateParameter('HuoYunZhuangTai', ftString, pdInput, 20, HuoYunZhuangTai);
      CreateParameter('ToCityCode', ftString, pdInput, 256, ToCityCode);
      CreateParameter('CheXing', ftString, pdInput, 100, CheXing);
      CreateParameter('CheXing_A', ftString, pdInput, 100, '');
      CreateParameter('CheXing_B', ftString, pdInput, 100, '');
      CreateParameter('CheXing_C', ftString, pdInput, 100, '');
      CreateParameter('CheXing_D', ftString, pdInput, 100, '');
      CreateParameter('CheZhang', ftString, pdInput, 50, CheZhang);
      CreateParameter('CheGao', ftString, pdInput, 50, CheGao);
      CreateParameter('CheKuan', ftString, pdInput, 50, CheKuan);
      CreateParameter('DunWei', ftString, pdInput, 100, DunWei);
      CreateParameter('RongJi', ftString, pdInput, 50, RongJi);
      CreateParameter('ZhuCeFou', ftInteger, pdInput, 4, StateCode);
      CreateParameter('FaDongJiHao', ftString, pdInput, 50, FaDongJiHao);
      CreateParameter('CheJiaHaoMa', ftString, pdInput, 50, Name);
      CreateParameter('BaoXianKaHao', ftString, pdInput, 50, BaoXianKaHao);
      CreateParameter('GuaKaoDanWei', ftString, pdInput, 50, GuaKaoDanWei);
      CreateParameter('YunYingZhengShu', ftString, pdInput, 50, YunYingZhengShu);
      CreateParameter('CheZhuXingMing', ftString, pdInput, 50, CheZhuXingMing);
      CreateParameter('CheZhuXingBie', ftString, pdInput, 50, CheZhuXingBie);
      CreateParameter('CheZhuShenFenZhengHao', ftString, pdInput, 50, CheZhuShenFenZhengHao);
      CreateParameter('CheZhuDianHuaHaoMa', ftString, pdInput, 50, CheZhuDianHuaHaoMa);
      CreateParameter('CheZhuQiTaDianHua', ftString, pdInput, 50, CheZhuQiTaDianHua);
      CreateParameter('CheZhuShouJi', ftString, pdInput, 50, CheZhuShouJi);
      CreateParameter('CheZhuJiaTingZhuZhi', ftString, pdInput, 50, CheZhuJiaTingZhuZhi);
      CreateParameter('SiJiXingBie', ftString, pdInput, 50, SiJiXingBie);
      CreateParameter('SiJiShenFenZhengHao', ftString, pdInput, 50, SiJiShenFenZhengHao);
      CreateParameter('JiaShiZhiZhao', ftString, pdInput, 50, JiaShiZhiZhao);
      CreateParameter('SiJiJiaTingDianHua', ftString, pdInput, 50, SiJiJiaTingDianHua);
      CreateParameter('SiJiQiTaDianHua', ftString, pdInput, 50, SiJiQiTaDianHua);
      CreateParameter('SiJiJiaTingZhuZhi', ftString, pdInput, 100, SiJiJiaTingZhuZhi);
      CreateParameter('BeiZhu', ftString, pdInput, 1000, BeiZhu);
      CreateParameter('SuoShuYongHu', ftInteger, pdInput, 50, SuoShuYongHu);
      CreateParameter('InfoType', ftInteger, pdInput, 4, 1);
      CreateParameter('ReturnCode', ftInteger, pdOutput, 4, 0);
      Conn.ExecStoredProc(Result.ErrCode, Result.ErrMsg, True);
      if Result.ErrCode = 0 then Vehicle.GUID := ParamValues['ReturnCode'];
      Callback(Result, Param);
    end;
  finally
    ConnPool.ReleaseConnection(Conn);
  end;
end;

procedure TADODatabase.AddPriVehicle(Vehicle: TVehicle;
  Param: Pointer; Callback: TSimpleCallback);
begin
  PriVehicleOperation(opAdd, Vehicle, Param, Callback);
end;

procedure TADODatabase.AddToTrack(const Phone: AnsiString; LocType: TLbmpLocType;
  LocTime: TDateTime; CityID: Integer; const Longitude, Latitude: AnsiString;
  const Address: WideString; Param: Pointer; Callback: TSimpleCallback);
begin

end;

constructor TADODatabase.Create;
begin
  CoInitialize(nil);
end;

destructor TADODatabase.Destroy;
begin
  CoUninitialize;
  inherited;
end;

procedure TADODatabase.GetAgencyInfo(CityCode: Integer; Agency: TAgency;
  Param: Pointer; Callback: TSimpleCallback);
var
  Result: TFuncCallResult;
begin
  GetRow(WideFormat('select top 1 [UserEmail] as Telephone, ' +
    '[UserName] as RealName from [cxt_56888_net].[dbo].[Rights_Users] ' +
    'where UserAgentCity like ''%%%d%%'' order by len(UserID)', [CityCode]),
    Agency, Result.ErrCode, Result.ErrMsg);
  Callback(Result, Param);
end;

procedure TADODatabase.GetLocPerson(UserID, PageIndex, PageSize: Integer;
  Filter: TLocPersonFilter; list: TDzPersistentList; 
  Param: Pointer; Callback: TSimpleCallback);
var
  Conn: TDBConnection;
  OrderBy: WideString;
  CondsObj: array [0..19] of Byte;
  Conds: TDzWideStrStream;
  Result: TFuncCallResult;
  function MapFiledName(const s: string): string;
  begin
    if (SameText(s, 'Phone')) then Result := 'SuiCheShouJi'
    else if (SameText(s, 'Name')) then Result := 'SiJiXingMing'
    else if (SameText(s, 'LastLocateTime')) then Result := 'DingWeiShiJian'
    else if (SameText(s, 'Position')) then Result := 'CheLiangWeiZhi'
    else if (SameText(s, 'Address')) then Result := 'WeiZhiMiaoShu'
    else if (SameText(s, 'LSSText')) then Result := 'ZhuCeFou'
    else Result := s;
  end;
begin
  Conn := ConnPool.GetConnection;
  if not Assigned(Conn) then
  begin
    SystemBusy(Result);
    Callback(Result, Param);
    Exit;
  end;
  Conds := TDzWideStrStream(TDzWideStrStream.InitInstance(@CondsObj));
  Conds.Size := 512;
  Conds.WriteString(WideFormat('A.Car_Del = 0 and A.SuoShuYongHu = %d and ' +
    'A.Car_InfoType = 2', [UserID]));
  try
    if Filter.Enabled then
    begin
      AddLikeCond(Conds, 'A.SiJiXingMing', Filter.PersonName);
      AddLikeCond(Conds,'A.SuiCheShouJi', Filter.Phone);
      AddEqualCond(Conds, 'A.SiJiXingBie', Filter.Sex);
      if Filter.CityCodes <> '' then
      begin
        if Conds.Position > 0 then Conds.WriteString(' and ');
        Conds.WriteString('A.CityCode in (');
        Conds.WriteString(Filter.CityCodes);
        Conds.WriteString(')');
      end;
    end;
    if Filter.SortFields = '' then OrderBy := ''
    else begin
      case Filter.SortDirection of
        sdNone: OrderBy := '';
        sdAscendent: OrderBy := MapFiledName(Filter.SortFields) + ' asc';
        sdDescendent: OrderBy := MapFiledName(Filter.SortFields) + ' desc';
      end;
    end;
    if OrderBy = '' then OrderBy := 'CheLiangBianHao'
    else OrderBy := OrderBy + ', CheLiangBianHao';
    Conds.Size := Conds.Position;
    GetPagedRecords(Conn, PageIndex + 1, PageSize,
      'CheLiangBianHao',
      'CheLiangBianHao as [GUID], SuiCheShouJi as [Phone], ' +
      'SiJiXingMing as [Name], SiJiXingBie as Sex, CityCode as CityID, ' +
      'DingWeiShiJian as LastLocateTime, ZhuCeFou as StateCode, ' +
      'CheLiangWeiZhi as [Position], WeiZhiMiaoShu as [Address], ' +
      'JingDu as Longitude, WeiDu as Latitude, BeiZhu as Remark',
      '[cxt_56888_net].[dbo].CarInfo A',
      Conds.DataString, OrderBy, Result.AsInteger, Result.ErrCode, Result.ErrMsg);
    if Result.ErrCode = 0 then
    begin
      try
        List.LoadFromDataSet(Conn.StoredProc);
      except
        Result.ErrCode := CXT_E_SERIALIZING;
        Result.ErrMsg := SCodecError;
      end;
    end;
    Callback(Result, Param);
  finally
    Conds.Size := 0;
    ConnPool.ReleaseConnection(Conn);
  end;
end;

procedure TADODatabase.GetTrack(const Phone: string; List: TDzPersistentList;
  Param: Pointer; Callback: TSimpleCallback);
var
  Conn: TDBConnection;
  Result: TFuncCallResult;
begin
  Conn := ConnPool.GetConnection;
  if not Assigned(Conn) then
  begin
    SystemBusy(Result);
    Callback(Result, Param);
    Exit;
  end;
  try
    Conn.ExecSQL(WideFormat('select top 100 CheLiangWeiZhi as [Position], ' +
      'JingDu as Longitude, WeiDu as Latitude, LocType - 1 as [LocType], ' +
      'AddTime as LocateTime, WeiZhiMiaoShu as Address ' +
      'from [cxt_56888_net].[dbo].[CheLiangGuiJi] ' +
      'where ShouJiHaoMa = %s order by [ID] desc', [Phone]),
      Result.ErrCode, Result.ErrMsg);
    if Result.ErrCode = 0 then
    begin
      try
        list.LoadFromDataSet(Conn.Query);
      except
        CodecError(Result);
      end;
    end;
    Callback(Result, Param);
  finally
    ConnPool.ReleaseConnection(Conn);
  end;
end;

procedure TADODatabase.GetLocTrace(ID: Integer; Tracing: TLocTrace; 
  Param: Pointer; Callback: TSimpleCallback);
var
  Conn: TDBConnection;
  Result: TFuncCallResult;
begin
  Conn := ConnPool.GetConnection;
  if not Assigned(Conn) then
  begin
    SystemBusy(Result);
    Callback(Result, Param);
    Exit;
  end;
  try
    Tracing.CarID := ID;
    Conn.ExecSQL(WideFormat('select A.*, B.ChePaiHaoMa as ' +
      'PlateNumber from [cxt_56888_net].[dbo].CarInfo_AutoLoc A inner join ' +
      '[cxt_56888_net].[dbo].CarInfo B on A.CarID = B.CheLiangBianHao ' +
      'where A.CarID = %d', [ID]), Result.ErrCode, Result.ErrMsg);
    if Result.ErrCode <> 0 then
    begin 
      Callback(Result, Param);
      Exit; 
    end;
    if Conn.Query.IsEmpty then Result.ErrCode := CXT_E_NO_DATA
    else try
      Tracing.Load(Conn.ClassReader);
    except
      CodecError(Result);
    end;
    Callback(Result, Param);
  finally
    ConnPool.ReleaseConnection(Conn);
  end;
end;

procedure TADODatabase.GetPriVehicle(UserID, PageSize, PageIndex: Integer;
  Filter: TPriVehicleFilter; List: TDzPersistentList;
  Param: Pointer; Callback: TSimpleCallback);
var
  Conn: TDBConnection;
  CondsObj: array [0..19] of Byte;
  Conds: TDzWideStrStream;
  OrderBy: WideString;
  Result: TFuncCallResult;
  function MapFiledName(const s: string): string;
  begin
    if SameText(s, 'Phone') then Result := 'SuiCheShouJi'
    else if SameText(s, 'Name') then Result := 'ChePaiHaoMa'
    else if SameText(s, 'LastLocateTime') then Result := 'DingWeiShiJian'
    else if SameText(s, 'Position') then Result := 'CheLiangWeiZhi'
    else if SameText(s, 'Address') then Result := 'WeiZhiMiaoShu'
    else if SameText(s, 'LSSText') then Result := 'ZhuCeFou'
    else if SameText(s, 'StateCode') then Result := 'ZhuCeFou'
    else Result := s;
  end;
begin
  Conn := ConnPool.GetConnection;
  if not Assigned(Conn) then
  begin
    SystemBusy(Result);
    Callback(Result, Param);
    Exit;
  end;
  Conds := TDzWideStrStream(TDzWideStrStream.InitInstance(@CondsObj));
  Conds.Size := 1024;
  Conds.WriteString(WideFormat('(A.Car_Del = 0) and (A.SuoShuYongHu = %d) ' +
    'and ((A.Car_InfoType = 1) or (Car_InfoType = 3))', [UserID]));
  try
    if Filter.Enabled then
    begin
      case Filter.Locatable of
        nbFalse: AddCondition(Conds, '(A.ZhuCeFou <> 3)');
        nbTrue: AddCondition(Conds, '(A.ZhuCeFou = 3)');
      end;
      AddLikeCond(Conds, 'A.SiJiXingMing', Filter.SiJiXingMing);
      AddLikeCond(Conds, 'A.ChePaiHaoMa', Filter.ChePaiHaoMa);
      AddLikeCond(Conds, 'A.SuiCheShouJi', Filter.Phone);
      AddLikeCond(Conds, 'A.CheZhang', Filter.CheZhang);
      AddLikeCond(Conds, '(A.BeiZhu', Filter.BeiZhu);
      AddLikeCond(Conds, 'A.CheGao', Filter.CheGao);
      AddLikeCond(Conds, 'A.CheXing_A', Filter.TuoGuaLunZhou);
      AddLikeCond(Conds, 'A.CheXing_B', Filter.HuoXiangJieGou);
      AddLikeCond(Conds, 'A.CheXing_C', Filter.TeShuGongNeng);
      AddLikeCond(Conds, 'A.CheXing_D', Filter.ChangShangPinPai);
      if Filter.ToCityCode <> '' then
      begin
        if Conds.Position > 0 then Conds.WriteString(' and ');
        Conds.WriteString('exists(select ID from CarInfo_ToCityCode ' +
          'where CheLiangBianHao = A.CheLiangBianHao and ToCityCode in (');
        Conds.WriteString(Filter.ToCityCode);
        Conds.WriteString('))');
      end;
      if Filter.InCityCode <> '' then
      begin
        if Conds.Position > 0 then Conds.WriteString(' and ');
        Conds.WriteString('A.CityCode in (');
        Conds.WriteString(Filter.InCityCode);
        Conds.WriteString(')');
      end;
    end;
    if Filter.SortFields = '' then OrderBy := ''
    else begin
      case Filter.SortDirection of
        sdNone: OrderBy := '';
        sdAscendent: OrderBy := MapFiledName(Filter.SortFields) + ' asc';
        sdDescendent: OrderBy := MapFiledName(Filter.SortFields) + ' desc';
      end;
    end;
    if OrderBy = '' then OrderBy := 'CheLiangBianHao'
    else OrderBy := OrderBy + ', CheLiangBianHao';
    Conds.Size := Conds.Position;
    GetPagedRecords(Conn, PageIndex + 1,PageSize,
      'CheLiangBianHao',
      'CheLiangBianHao as [GUID], SuoShuYongHu, SuiCheShouJi as Phone, ' +
      'ChePaiHaoMa as [Name], SiJiXingMing, ' +
      'QiWangLiuXiang, CheXing, HuoYunZhuangTai, CheZhang, CheKuan, CheGao, ' +
      'DunWei, RongJi, BeiZhu, FaDongJiHao, CheJiaHaoMa, BaoXianKaHao, ' +
      'GuaKaoDanWei, YunYingZhengShu, CityCode as CityID, ' +
      'DingWeiShiJian as [LastLocateTime], CheLiangWeiZhi as [Position], ' +
      'CheZhuXingMing, CheZhuShouJi, CheZhuShenFenZhengHao, CheZhuXingBie, ' +
      'CheZhuDianHuaHaoMa, CheZhuQiTaDianHua, CheZhuJiaTingZhuZhi, ' +
      'SiJiShenFenZhengHao, SiJiXingBie, JiaShiZhiZhao, SiJiJiaTingDianHua, ' +
      'SiJiQiTaDianHua, SiJiJiaTingZhuZhi, Car_AddTime, ' +
      'WeiZhiMiaoShu as Address, ZhuCeFou as StateCode, JingDu as Longitude, ' +
      'WeiDu as Latitude',
      '[cxt_56888_net].[dbo].CarInfo A',
      Conds.DataString, OrderBy, Result.AsInteger, Result.ErrCode, Result.ErrMsg);
    if Result.ErrCode <> 0 then
    begin
      Callback(Result, Param);
      Exit;
    end;
    try
      List.LoadFromDataSet(Conn.StoredProc);
    except
      Result.ErrCode := CXT_E_SERIALIZING;
      Result.ErrMsg := SCodecError;
    end;
    Callback(Result, Param);
  finally
    Conds.Size := 0;
    ConnPool.ReleaseConnection(Conn);
  end;
end;

procedure TADODatabase._GetShareVehicle(ObjType: TLBSObjectType; 
  Filter: TShareVehicleFilter; PageIndex, PageSize: Integer; 
  List: TDzPersistentList; Param: Pointer; Callback: TSimpleCallback);
var
  OrderBy: WideString;
  CondsObj: array [0..19] of Byte;
  Conds: TDzWideStrStream;
  TypeID: Integer;
  Conn: TDBConnection;
  Fields: WideString;
  Result: TFuncCallResult;
  function MapFiledName(const s: string): string;
  begin
    if SameText(s, 'Phone') then Result := 'SuiCheShouJi'
    else if SameText(s, 'Name') then Result := 'ChePaiHaoMa'
    else if SameText(s, 'LastLocateTime') then Result := 'DingWeiShiJian'
    else if SameText(s, 'Position') then Result := 'CheLiangWeiZhi'
    else if SameText(s, 'Address') then Result := 'WeiZhiMiaoShu'
    else if SameText(s, 'LSSText') then Result := 'ZhuCeFou'
    else if SameText(s, 'UserName') then Result := 'B.Use_UserName'
    else if SameText(s, 'UserCompany') then Result := 'B.Use_Corp'
    else if SameText(s, 'UserTelephone') then Result := 'B.Use_Tel'
    else if SameText(s, 'UserMobile') then Result := 'B.Use_MobileNo'
    else Result := s;
  end;
begin
  Conn := ConnPool.GetConnection;
  if not Assigned(Conn) then
  begin
    SystemBusy(Result);
    Callback(Result, Param);
    Exit;
  end;
  if ObjType = otShare then TypeID := 1
  else TypeID := 2;
  Conds := TDzWideStrStream(TDzWideStrStream.InitInstance(@CondsObj));
  Conds.Size := 1024;
  Conds.WriteString(WideFormat('A.Car_Del = 0 and A.Car_InfoType = 1 ' +
      'and A.Car_Source = %d', [TypeID]));
  try
    if Filter.Enabled then
    begin
      case Filter.Locatable of
        nbTrue: AddCondition(Conds, 'A.ZhuCeFou = 3');
        nbFalse: AddCondition(Conds, 'A.ZhuCeFou <> 3');
      end;
      AddLikeCond(Conds, 'A.CheKuan' , Filter.CheKuan);
      AddLikeCond(Conds, 'A.RongJi', Filter.RongJi);
      AddEqualCond(Conds, 'A.DunWei', Filter.DunWei);
      AddEqualCond(Conds, 'A.CheZhang', Filter.CheZhang);
      AddLikeCond(Conds, 'A.BeiZhu', Filter.BeiZhu);
      AddLikeCond(Conds, 'A.CheGao', Filter.CheGao);
      AddLikeCond(Conds, 'A.CheXing_A', Filter.TuoGuaLunZhou);
      AddLikeCond(Conds, 'A.CheXing_B', Filter.HuoXiangJieGou);
      AddLikeCond(Conds, 'A.CheXing_C', Filter.TeShuGongNeng);
      AddLikeCond(Conds, 'A.CheXing_D', Filter.ChangShangPinPai);
      if Filter.ToCityCode <> '' then
      begin
        if Conds.Position > 0 then Conds.WriteString(' and ');
        Conds.WriteString('exists(select ID from CarInfo_ToCityCode ' +
          'where CheLiangBianHao = A.CheLiangBianHao and ToCityCode in (');
        Conds.WriteString(Filter.ToCityCode);
        Conds.WriteString('))');
      end;
      if Filter.InCityCode <> '' then
      begin
        if Conds.Position > 0 then Conds.WriteString(' and ');
        Conds.WriteString('A.CityCode in (');
        Conds.WriteString(Filter.InCityCode);
        Conds.WriteString(')');
      end;
    end;
    if ObjType = otShare then
      Fields := 'A.CheLiangBianHao as [GUID], A.ChePaiHaoMa as [Name], ' +
        'A.SuiCheShouJi as Phone, A.SiJiXingMing, A.QiWangLiuXiang, ' +
        'A.CheXing, A.CheZhang, A.CheKuan, A.CheGao, A.ZhuCeFou as [StateCode], ' +
        'A.DunWei, case when A.ZhuCeFou = 3 then A.CheLiangWeiZhi else ' +
        'A.CheLiangWeiZhi2 end as [Position], A.WeiZhiMiaoShu as Address, ' +
        'A.Jingdu as Longitude, A.Weidu as Latitude, CityCode as CityID, ' +
        'case when A.ZhuCeFou = 3 then A.DingWeiShiJian ' +
        'else A.Car_AddTime end as LastLocateTime, ' +
        'A.SuoShuYongHu, B.use_UserName as UserName, ' +
        'B.use_Corp as UserCompany, B.Use_Tel as UserTelephone, ' +
        'B.Use_MobileNo as UserMobile, CityCode'
    else
      Fields := 'A.CheLiangBianHao as [GUID], A.ChePaiHaoMa as [Name], ' +
        'A.SuiCheShouJi as Phone, A.SiJiXingMing, A.QiWangLiuXiang, ' +
        'A.CheXing, A.CheZhang, A.CheKuan, A.CheGao, A.ZhuCeFou as [StateCode], ' +
        'A.DunWei, case when A.ZhuCeFou = 3 then A.CheLiangWeiZhi else ' +
        'A.CheLiangWeiZhi2 end as [Position], A.WeiZhiMiaoShu as Address, ' +
        'A.Jingdu as Longitude, A.Weidu as Latitude, CityCode as CityID, ' +
        'case when A.ZhuCeFou = 3 then A.DingWeiShiJian ' +
        'else A.Car_AddTime end as LastLocateTime, ' +
        'A.SuoShuYongHu, B.use_UserName as UserName, ' +
        'B.use_Corp as UserCompany, B.Use_Tel as UserTelephone, ' +
        'B.Use_MobileNo as UserMobile, CityCode';
    if Filter.SortFields = '' then OrderBy := ''
    else begin
      case Filter.SortDirection of
        sdNone: OrderBy := '';
        sdAscendent: OrderBy := MapFiledName(Filter.SortFields) + ' asc';
        sdDescendent: OrderBy := MapFiledName(Filter.SortFields) + ' desc';
      end;
    end;
    if OrderBy = '' then OrderBy := 'CheLiangBianHao'
    else OrderBy := OrderBy + ', CheLiangBianHao';
    Conds.Size := Conds.Position;
    GetPagedRecords(Conn, PageIndex + 1, PageSize, 'A.CheLiangBianHao', Fields,
      '[cxt_56888_net].[dbo].[CarInfo] A left join [cxt_56888_net].[dbo].Users B ' +
      'on A.SuoShuYongHu = B.Use_ID', Conds.DataString, OrderBy,
      Result.TtlRecord, Result.ErrCode, Result.ErrMsg);

    if Result.ErrCode = 0 then
    begin 
      try
        List.LoadFromDataSet(Conn.StoredProc);
      except
        CodecError(Result);
      end;
    end;
    Callback(Result, Param);
  finally
    Conds.Size := 0;
    ConnPool.ReleaseConnection(Conn);
  end;
end;

procedure TADODatabase.GetShareVehicle(Filter: TShareVehicleFilter;
  PageIndex, PageSize: Integer; List: TDzPersistentList;
  Param: Pointer; Callback: TSimpleCallback);
begin 
  _GetShareVehicle(otShare, Filter, PageIndex, PageSize, List, Param, Callback);
end;

procedure TADODatabase.GetWebShareVehicle(Filter: TWebShareVehicleFilter;
  PageIndex, PageSize: Integer; List: TDzPersistentList;
  Param: Pointer; Callback: TSimpleCallback);
begin 
  _GetShareVehicle(otWebShare, Filter, PageIndex, PageSize, List, Param, Callback);
end;

procedure TADODatabase.GetUserInfo(const ComputerID, UserName: AnsiString;
  UserInfo: TUserInfo; Param: Pointer; Callback: TSimpleCallback);
var
  Conn: TDBConnection;
  Result: TFuncCallResult;
const
  SQLFMT = 'select A.[Use_State] as UserState, A.[Use_ID] as UserID, ' +
    'A.[Use_UserName] as UserName, ' +
    'A.[Use_RealName] as RealName, A.[Use_IDCardNo] as IDCardNo, ' +
    'A.[Use_Sex] as Sex, A.[Use_Password] as [Password], A.Use_Type as UserType, ' +
    'A.[Use_CreateTime] as CreateTime, A.[Use_LastLogin] as LastLoginTime, ' +
    'A.[Use_CityCode] as CityCode, A.[Use_Add] as [Address], ' +
    'A.[Use_Corp] as CompanyName, A.[Use_Tel] as Telephone, ' +
    'A.Use_CityCode as CityCode, A.[Use_MobileNo] as MobilePhone, ' +
    'A.[Use_Url] as Website, A.[Use_smsPoint] as SmsPoint, ' +
    'A.[Use_LocPoint] as LocPoint, ' +
    'A.[Use_LocationTime] as AutoLocateTime, A.Use_DiskKeyNo as ComputerID, ' +
    'A.Use_DiskKeyNo2 as ComputerID2, B.UserEmail as AgentTel, ' +
    'A.[Contract], A.Use_IsBlock as [Blocked], A.BlockReason, C.Reason ' +
    'from [cxt_56888_net].[dbo].[Users] A left outer join ' +
    '[cxt_56888_net].[dbo].[Rights_Users] B on B.UserAgentCity like ' +
    '''%%'' + convert(varchar(10), A.Use_CityCode) + ''%%'' left outer join ' +
    '[cxt_56888_net].[dbo].[LockedComputers] C on C.ComputerID = A.Use_DiskKeyNo or ' +
    'C.ComputerID = A.Use_DiskKeyNo2 where A.Use_UserName = ''%s'' and A.Use_State > 0';
begin
  Conn := ConnPool.GetConnection;
  if not Assigned(Conn) then
  begin
    SystemBusy(Result);
    Callback(Result, Param);
    Exit;
  end;

  with Conn.Query do  
  try
    Conn.ExecSQL(WideFormat(SQLFMT, [UserName]), Result.ErrCode, Result.ErrMsg);
    if Result.ErrCode = 0 then
    begin
      if IsEmpty then
      begin
        Result.ErrCode := CXT_E_NO_DATA;
        Result.ErrMsg := '';
        Callback(Result, Param);
        Exit;
      end;
      UserInfo.AgentTel := Fields[FieldCount - 5].AsString; 
      if not Fields[FieldCount - 4].IsNull and
        not Fields[FieldCount - 4].AsBoolean then
      begin
        UserInfo.DoContract := nbFalse;
      end
      else begin
        if Fields[FieldCount - 4].IsNull then UserInfo.DoContract := nbNull
        else UserInfo.DoContract := nbTrue;
        if Fields[FieldCount - 1].IsNull then
        begin
          if Fields[FieldCount - 3].IsNull or (Fields[FieldCount - 3].AsInteger = 0) then
          begin
            Result.Locked := False;
            Result.WideStr := '';
            try
              UserInfo.Load(Conn.ClassReader);
            except
              CodecError(Result);
            end;
          end
          else begin
            Result.Locked := True;
            Result.WideStr := Fields[FieldCount - 2].AsWideString;
          end;
        end
        else begin
          Result.Locked := True;
          Result.WideStr := Conn.Query.Fields[Conn.Query.FieldCount - 1].AsWideString;
        end;
      end;
    end;
    Callback(Result, Param);
  finally
    ConnPool.ReleaseConnection(Conn);
  end;
end;

procedure TADODatabase.GetUserLocatePoint(UserID: Integer; Param: Pointer;
  Callback: TSimpleCallback);
var
  LocPoint: Variant;
  Result: TFuncCallResult;
begin
  GetSingleField(WideFormat('select Use_LocPoint from [cxt_56888_net].[dbo].[Users] ' +
    'where [Use_ID] = %d', [UserID]), '', LocPoint, Result.ErrCode, Result.ErrMsg);
  if Result.ErrCode = 0 then Result.LocPoint := LocPoint;
  Callback(Result, Param);
end;

procedure TADODatabase.GetUserSmsPoint(UserID: Integer; Param: Pointer;
  Callback: TSimpleCallback);
var
  SmsPoint: Variant;
  Result: TFuncCallResult;
begin
  GetSingleField(WideFormat('select Use_SmsPoint from [cxt_56888_net].[dbo].[Users] ' +
    'where [Use_ID] = %d', [UserID]), '', SmsPoint, Result.ErrCode, Result.ErrMsg);
  if Result.ErrCode = 0 then Result.SmsPoint := SmsPoint;
  Callback(Result, Param);
end;

procedure TADODatabase.IsComputerLocked(const ComputerID: AnsiString;
  Param: Pointer; Callback: TSimpleCallback);
var
  Reason: Variant;
  Result: TFuncCallResult;
begin
  GetSingleField(WideFormat('select Reason from cxt_56888_net.dbo.LockedComputers ' +
    'where ComputerID = ''%s''', [WideString(ComputerID)]), '', Reason,
    Result.ErrCode, Result.ErrMsg);
  if Result.ErrCode = 0 then  
  begin
    Result.Locked := True;
    Result.WideStr := Reason;
  end
  else if Result.ErrCode = CXT_E_NO_DATA then
  begin
    Result.ErrCode := CXT_E_SUCCESS;
    Result.ErrMsg := '';
    Result.Locked := False;
    Result.WideStr := '';
  end;
  Callback(Result, Param);
end;

procedure TADODatabase.LockComputer(const ComputerID: AnsiString;
  const Reason: WideString; Param: Pointer; Callback: TSimpleCallback);
var
  Result: TFuncCallResult;
begin
  ExecCommand(WideFormat('exec cxt_56888_net.dbo.LockComputer ''%s'', ''%s''',  
    [WideString(ComputerID), Reason]), Result.ErrCode, Result.ErrMsg);
  Callback(Result, Param);
end;

procedure TADODatabase.LockUserByID(UserID: Integer; const ComputerID: AnsiString;  
  const Reason: WideString; Param: Pointer; Callback: TSimpleCallback);
var
  Result: TFuncCallResult;
begin
  if ComputerID = '' then
  begin
    ExecCommand(WideFormat('update [cxt_56888_net].[dbo].[Users] set Use_IsBlock = 1, ' +
      'BlockReason = '#39'%s'#39' where Use_ID = %d', [Reason, UserID]),
      Result.ErrCode, Result.ErrMsg);
    Callback(Result, Param);
  end
  else LockComputer(ComputerID, Reason, Param, Callback);
end;

procedure TADODatabase.ModifyAccount(UserInfo: TUserInfo; Param: Pointer;
  Callback: TSimpleCallback);
var
  Conn: TDBConnection;
  Result: TFuncCallResult;
begin
  Conn := ConnPool.GetConnection;
  if not Assigned(Conn) then
  begin
    SystemBusy(Result);
    Callback(Result, Param);
    Exit;
  end;
  with Conn, Conn.StoredProc, Conn.StoredProc.Parameters do
  try
    ProcedureName := '[cxt_56888_net].[dbo].[Users_ModifyUser]';
    Clear;
    CreateParameter('Use_UserID', ftInteger, pdInput, 4, UserInfo.UserID);
    CreateParameter('Use_Type', ftInteger, pdInput, 4, UserInfo.UserType);
    CreateParameter('Use_RealName', ftString, pdInput, 20, UserInfo.RealName);
    CreateParameter('Use_Sex', ftInteger, pdInput, 4, UserInfo.Sex);
    CreateParameter('Use_IDCardNo', ftString, pdInput, 18, UserInfo.IDCardNo);
    CreateParameter('Use_CityCode', ftInteger, pdInput, 4, UserInfo.CityCode);
    CreateParameter('Use_Tel', ftString, pdInput, 20, UserInfo.Telephone);
    CreateParameter('Use_Add', ftString, pdInput, 500, UserInfo.Address);
    CreateParameter('Use_Corp', ftString, pdInput, 500, UserInfo.CompanyName);
    CreateParameter('Use_MobileNo', ftString, pdInput, 20, UserInfo.MobilePhone);
    CreateParameter('Use_Url', ftString, pdInput, 100, UserInfo.Website);
    ExecStoredProc(Result.ErrCode, Result.ErrMsg, True);
    Callback(Result, Param);
  finally
    ConnPool.ReleaseConnection(Conn);
  end;
end;

procedure TADODatabase.ModifyLocPerson(Person: TLocPerson;
  Param: Pointer; Callback: TSimpleCallback);
var
  Conn: TDBConnection;
  Result: TFuncCallResult;
begin
  Conn := ConnPool.GetConnection;
  if not Assigned(Conn) then
  begin
    SystemBusy(Result);
    Callback(Result, Param);
    Exit;
  end;
  Result.NumProcessed := 0;
  with Conn, StoredProc.Parameters do
  try
    StoredProc.ProcedureName := '[cxt_56888_net].[dbo].[CarInfo_UpdatePeopleInfo]';
    Clear;
    CreateParameter('SuiCheShouJi',ftString, pdInput, 50, null);
    CreateParameter('SiJiXingMing', ftString, pdInput, 50, null);
    CreateParameter('Sex', ftString, pdInput, 2, null);
    CreateParameter('BeiZhu', ftString, pdInput, 1000, null);
    CreateParameter('CheLiangBianHao', ftInteger, pdInput, 4, null);
    CreateParameter('SuoShuYongHu', ftInteger, pdInput, 4, null);
    CreateParameter('ReturnCode', ftInteger, pdOutput, 4, null);
    Items[0].Value := Person.Phone;
    Items[1].Value := Person.Name;
    Items[2].Value := Person.Sex;
    Items[3].Value := Person.Remark;
    Items[4].Value := Person.GUID;
    Items[5].Value := Person.UserID;
    ExecStoredProc(Result.ErrCode, Result.ErrMsg, True);
    Callback(Result, Param);
  finally
    ConnPool.ReleaseConnection(Conn);
  end;
end;

procedure TADODatabase.ModifyLBMPState(const Phone: AnsiString; State: Integer;
  Param: Pointer; Callback: TSimpleCallback);
var
  Result: TFuncCallResult;
begin
  ExecCommand(WideFormat('update [cxt_56888_net].[dbo].[CarInfo] ' +
    'set [ZhuCeFou] = %d where [SuiCheShouJi] = ''%s''',
    [State, WideString(Phone)]), Result.ErrCode, Result.ErrMsg);
  Callback(Result, Param);
end;

procedure TADODatabase.ModifyLocTrace(Tracing: TLocTrace; Param: Pointer;
  Callback: TSimpleCallback);
var
  Conn: TDBConnection;
  Result: TFuncCallResult;
begin
  Conn := ConnPool.GetConnection;
  if not Assigned(Conn) then
  begin
    SystemBusy(Result);
    Callback(Result, Param);
    Exit;
  end;
  try
    with Conn.StoredProc, Conn.StoredProc.Parameters do 
    begin
      Clear;
      ProcedureName := '[cxt_56888_net].[dbo].[CarInfo_AutoLoc_AddUpdate]';
      CreateParameter('AutoLocID', ftInteger, pdInput, 4, Tracing.AutoLocID);
      CreateParameter('CarID', ftInteger, pdInput, 4, Tracing.CarID);
      CreateParameter('UserID', ftInteger, pdInput, 4, Tracing.UserID);
      CreateParameter('CarMobile', ftWideString, pdInput, 32, Tracing.CarMobile);
      CreateParameter('InMobile', ftWideString, pdInput, 128, Tracing.InMobile);
      CreateParameter('ToMobile', ftWideString, pdInput, 128, Tracing.ToMobile);
      CreateParameter('TimeSlot', ftWideString, pdInput, 72, Tracing.TimeSlot);
      CreateParameter('StartTime', ftDateTime, pdInput, 8, Tracing.StartTime);
      CreateParameter('StopTime', ftDateTime, pdInput, 8, Tracing.StopTime);
      CreateParameter('SmsContent', ftWideString, pdInput, 256, Tracing.SmsContent);
      CreateParameter('AutoLocIsOpen', ftInteger, pdInput, 4, 1);
      CreateParameter('ReturnCode', ftInteger, pdOutput, 4, 0);
      Conn.ExecStoredProc(Result.ErrCode, Result.ErrMsg, True);
      Callback(Result, Param);
    end;  
  finally
    ConnPool.ReleaseConnection(Conn);
  end;
end;

procedure TADODatabase.ModifyPassword(UserID: Integer; const OldPwd, NewPwd: AnsiString;
  Param: Pointer; Callback: TSimpleCallback);
var
  Conn: TDBConnection;
  ReturnCode: Integer;
  Result: TFuncCallResult;
begin
  Conn := ConnPool.GetConnection;
  if not Assigned(Conn) then
  begin
    SystemBusy(Result);
    Callback(Result, Param);
    Exit;
  end;
  with Conn, Conn.StoredProc, Conn.StoredProc.Parameters do
  try
    ProcedureName := '[cxt_56888_net].[dbo].[Users_EditPassword]';
    Clear;
    CreateParameter('Use_ID', ftInteger, pdInput, 4, UserID);
    CreateParameter('Use_Password', ftString, pdInput, 50, NewPwd);
    CreateParameter('OldPassword', ftString, pdInput, 50, OldPwd);
    CreateParameter('ReturnCode', ftInteger, pdOutput, 4, null);
    ExecStoredProc(Result.ErrCode, Result.ErrMsg, True);
    if Result.ErrCode = 0 then
    begin
      ReturnCode := ParamValues['ReturnCode'];
      case ReturnCode of
        0: ;
        1:
          begin
            Result.ErrCode := CXT_E_NO_DATA;
            Result.ErrMsg := '';
          end;
        else begin
          Result.ErrCode := CXT_E_AUTHENTICATION;
          Result.ErrMsg := SErrorPassword;
        end;
      end;
    end;
    Callback(Result, Param);
  finally
    ConnPool.ReleaseConnection(Conn);
  end;
end;

procedure TADODatabase.ModifyPriVehicle(Vehicle: TVehicle;
  Param: Pointer; Callback: TSimpleCallback);
begin
  PriVehicleOperation(opModify, Vehicle, Param, Callback);
end;

procedure TADODatabase.RemoveLocPerson(List: TDzPersistentList;
  Param: Pointer; Callback: TSimpleCallback);
begin
  RemovePriVehicle(List, Param, Callback);
end;

procedure TADODatabase.RemoveLocTrace(ID: Integer; Param: Pointer;
  Callback: TSimpleCallback);
var
  Result: TFuncCallResult;
begin
  ExecCommand(WideFormat('delete from [cxt_56888_net].[dbo].[CarInfo_AutoLoc] ' +
    'where AutoLocID = %d', [ID]), Result.ErrCode, Result.ErrMsg);
  Callback(Result, Param);
end;

procedure TADODatabase.SaveLocateResult(const Phone, Longitude, Latitude: AnsiString;
  const Address, CityName: WideString; CityID, UserID, ObjectID, Cost: Integer;
  LocType: TLbmpLocType; Param: Pointer; Callback: TSimpleCallback);
var
  Result: TFuncCallResult;
begin
  ExecCommand(WideFormat('exec cxt_56888_net.dbo.Car_UpdateLocation2 ' +
    '%d, ' +  //@AddToGuiJi int = 0
    '0, ' +  //@IsAutoLoc int = 0
    '%d, ' + //@LocPoint int = 0
    '%d, '+  //@LocType int = 0
    '%d, ' + //@SuoShuYongHu int
    '%d, '+  //@CheLiangBianHao int
    '''%s'', ' + //@ShouJiHaoMa varchar(50)
    '0, ' +  //@ErrorCode int
    '%d, ' + //@CityID int
    '''%s'', ' +  //@CityName nvarchar(80)
    '''%s'', ' +  //@Address nvarchar(100)
    '''%s'', ' +  //@Longitude varchar(20)
    '''%s'', ' +  //@Latitude varchar(20)
    '3'#13#10, //@StateCode int
    [Ord(not AppConfig.UseDWTrackServer), Cost, Ord(LocType) + 1,
    UserID, ObjectID, WideString(Phone), CityID, CityName,
    Address, WideString(Longitude), WideString(Latitude)]),
    Result.ErrCode, Result.ErrMsg);
  Callback(Result, Param);
end;

procedure TADODatabase.SaveLogin(UserID: Integer; LoginTime: TDateTime;
  const Source, ComputerID: AnsiString; Param: Pointer; Callback: TSimpleCallback);
var
  Result: TFuncCallResult;
begin
  ExecCommand(WideFormat('exec [cxt_56888_net].[dbo].[SaveLogin] ' +
    '%d, ''%s'', ''%s'', ''%s''',  [UserID, WideString(ComputerID),
    WideString(Source), FormatDateTime('yyyy-m-d hh:nn:ss', LoginTime)]),
    Result.ErrCode, Result.ErrMsg);
  Callback(Result, Param);
end;

procedure TADODatabase.SaveSms(const Sender, Recver, Content: WideString;
  SendTime: TDateTime; Param: Pointer; Callback: TSimpleCallback);
var
  Result: TFuncCallResult;
begin
  ExecCommand(WideFormat('insert into [cxt_56888_net].[dbo].[smsHistoryRec] ' +
    '([sms_Contents], [sms_AccNumber], [sms_UserName] ,[sms_AddTime]) values ' +
    '(''%s'', ''%s'', ''%s'', ''%s'')', [Content, Recver, Sender,
    FormatDateTime('yyyy-m-d hh:nn:ss', SendTime)]), Result.ErrCode, Result.ErrMsg);
  Callback(Result, Param);
end;

procedure TADODatabase.SetAutoLocTime(UserID, Hour: Integer;
  Param: Pointer; Callback: TSimpleCallback);
var
  Result: TFuncCallResult;
begin
  ExecCommand(WideFormat('update [cxt_56888_net].[dbo].Users ' +
    'set Use_LocationTime = %d where Use_ID = %d; ' +
    'update [cxt_56888_net].[dbo].CarInfo ' +
    'set AutoLocTime = %d where SuoShuYongHu = %d',
    [Hour, UserID, Hour, UserID]), Result.ErrCode, Result.ErrMsg);
  Callback(Result, Param);
end;

procedure TADODatabase.UnlockCompter(const ComputerID: AnsiString;
  Param: Pointer; Callback: TSimpleCallback);
var
  Result: TFuncCallResult;
begin
  ExecCommand(WideFormat('delete from [cxt_56888_net].[dbo].LockedComputers ' +
    'where ComputerID = ''%s''', [WideString(ComputerID)]),
    Result.ErrCode, Result.ErrMsg);
  Callback(Result, Param);  
end;

procedure TADODatabase.UpdateLocTrace(Tracing: TLocTrace;
  Param: Pointer; Callback: TSimpleCallback);
var
  Conn: TDBConnection;
  Result: TFuncCallResult;
begin
  Conn := ConnPool.GetConnection;
  if not Assigned(Conn) then
  begin
    SystemBusy(Result);
    Callback(Result, Param);
    Exit;
  end;
  try
    with Conn.StoredProc, Conn.StoredProc.Parameters do 
    begin
      Clear;
      ProcedureName := '[cxt_56888_net].[dbo].[CarInfo_AutoLoc_AddUpdate]';
      CreateParameter('AutoLocID', ftInteger, pdInput, 4, Tracing.AutoLocID);
      CreateParameter('CarID', ftInteger, pdInput, 4, Tracing.CarID);
      CreateParameter('UserID', ftInteger, pdInput, 4, Tracing.UserID);
      CreateParameter('CarMobile', ftWideString, pdInput, 32, Tracing.CarMobile);
      CreateParameter('InMobile', ftWideString, pdInput, 128, Tracing.InMobile);
      CreateParameter('ToMobile', ftWideString, pdInput, 128, Tracing.ToMobile);
      CreateParameter('TimeSlot', ftWideString, pdInput, 72, Tracing.TimeSlot);
      CreateParameter('StartTime', ftDateTime, pdInput, 8, Tracing.StartTime);
      CreateParameter('StopTime', ftDateTime, pdInput, 8, Tracing.StopTime);
      CreateParameter('SmsContent', ftWideString, pdInput, 256, Tracing.SmsContent);
      CreateParameter('AutoLocIsOpen', ftInteger, pdInput, 4, 1);
      CreateParameter('ReturnCode', ftInteger, pdOutput, 4, 0);
      Conn.ExecStoredProc(Result.ErrCode, Result.ErrMsg, True);
      Callback(Result, Param);
    end;  
  finally
    ConnPool.ReleaseConnection(Conn);
  end;
end;

procedure TADODatabase.DecUserLocatePoint(UserID, Quantity: Integer;
  Param: Pointer; Callback: TSimpleCallback);
var
  Result: TFuncCallResult;
begin
  ExecCommand(WideFormat('update cxt_56888_net.dbo.Users set Use_LocPoint = ' +
    'Use_LocPoint - %d where Use_ID = %d', [Quantity, UserID]), 
    Result.ErrCode, Result.ErrMsg);
  Callback(Result, Param);
end;

procedure TADODatabase.DecUserSmsPoint(UserID, Quantity: Integer;
  Param: Pointer; Callback: TSimpleCallback);
var
  Result: TFuncCallResult;
begin
  ExecCommand(WideFormat('update [cxt_56888_net].[dbo].[Users] ' +
    'set Use_SmsPoint = Use_SmsPoint - %d where [Use_ID] = %d',
    [Quantity, UserID]), Result.ErrCode, Result.ErrMsg);
  Callback(Result, Param);
end;

procedure TADODatabase.RemovePriVehicle(List: TDzPersistentList;
  Param: Pointer; Callback: TSimpleCallback);
const
  SQLCMD = 'update [cxt_56888_net].[dbo].[CarInfo] set Car_Del = 1 ' +
    'where Car_Del = 0 and ((1 = 0) ';
var
  i, num: Integer;
  def: TObjectKey;
  Conn: TDBConnection;
  Result: TFuncCallResult;
  procedure RemoveBatch;
  begin
    Conn.Query.SQL.Add(')');
    Conn.ExecSQL('', Result.ErrCode, Result.ErrMsg, True, @num);
    if Result.ErrCode = 0 then
    begin         
      Inc(Result.NumProcessed, num);
      Conn.Query.SQL.Clear;
      Conn.Query.SQL.Add(SQLCMD);
    end;
  end;
begin
  Conn := ConnPool.GetConnection;
  if not Assigned(Conn) then
  begin
    SystemBusy(Result);
    Callback(Result, Param);
    Exit;
  end;
  Result.NumProcessed := 0;
  Result.ErrCode := CXT_E_SUCCESS;
  with Conn.Query do
  try
    SQL.Clear;
    SQL.Add(SQLCMD);
    for i := 0 to List.Count - 1 do
    begin
      def := TObjectKey(List[i]);
      if (i mod 10 = 0) and (i <> 0) then
      begin
        RemoveBatch;
        if Result.ErrCode <> 0 then Break;
      end;
      SQL.Add(WideFormat('or (CheLiangBianHao = %d) ', [def.ObjectID]));
    end;
    if (Result.ErrCode = 0) and (SQL.Count > 1) then RemoveBatch;
  finally
    ConnPool.ReleaseConnection(Conn);
  end;
  if Result.NumProcessed > 0 then
  begin
    Result.ErrCode := CXT_E_SUCCESS;
    Result.ErrMsg := '';
  end;
  Callback(Result, Param);
end;

end.

